package com.greate.community.controller;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.greate.community.constant.CommunityConstant;
import com.greate.community.constant.ExpType;
import com.greate.community.entity.*;
import com.greate.community.entity.dto.AddPostDTO;
import com.greate.community.event.EventProducer;
import com.greate.community.service.*;
import com.greate.community.util.*;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.util.HtmlUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 帖子
 */
@Validated
@RestController
@RequestMapping("/discuss")
public class DiscussPostController extends BaseController implements CommunityConstant {

    @Autowired
    private ElasticsearchService elasticsearchService;

    @Autowired
    private DiscussPostService discussPostService;

    @Autowired
    private UserService userService;

    @Autowired
    private LikeService likeService;

    @Autowired
    private EventProducer eventProducer;

    /**
     * 添加帖子（发帖）
     *
     * @return
     */
    @PostMapping("/add")
    public Result addDiscussPost(@RequestBody @Validated AddPostDTO addPostDTO) {
        String title = addPostDTO.getTitle();
        String content = addPostDTO.getContent();
        List<String> picUrlList = addPostDTO.getPicUrls();

        List<String> filter = picUrlList.stream().filter(url -> !StringUtils.isBlank(url)).collect(Collectors.toList());

        String picUrls = StringListConvertor.join(filter);

        if (getUser() == null) {
            return new Result("forbidden", "403", "您还未登录");
        }

        DiscussPost discussPost = new DiscussPost();
        discussPost.setUserId(getUser().getId());
        discussPost.setTitle(title);
        discussPost.setContent(content);
        discussPost.setPicUrls(picUrls);
        discussPost.setViewCount(0);
        discussPost.setLikeCount(0);
        discussPost.setCommentCount(0);
        discussPost.setCreateTime(new Date());

        discussPostService.addDiscussPost(discussPost);

        // 触发发帖事件，通过消息队列将其存入 Elasticsearch 服务器
        Event publishEvent = new Event()
                .setTopic(TOPIC_PUBLISH)
                .setUserId(getUser().getId())
                .setEntityType(ENTITY_TYPE_POST)
                .setEntityId(discussPost.getId());
        eventProducer.fireEvent(publishEvent);

        // 触发增加经验事件
        Event expEvent = new Event()
                .setTopic(TOPIC_EXP)
                .setUserId(getUser().getId())
                .setData("type", ExpType.EXP_PUBLISH.getName());
        eventProducer.fireEvent(expEvent);

        // 计算帖子分数
//        String redisKey = RedisKeyUtil.getPostScoreKey();
//        redisTemplate.opsForSet().add(redisKey, discussPost.getId());

        return new Result("success", "200", "帖子发布成功，" + "配图 " + filter.size() + " 张");
    }

    /**
     * 查找首页帖子列表
     *
     * @param page
     * @param orderMode 默认是 0（最新）
     * @return
     */
    @GetMapping("/index")
    @ResponseBody
    public Result getIndexPage(Page page, @RequestParam(name = "orderMode", defaultValue = "0") int orderMode) {
        HashMap<String, Object> hashMap = new HashMap<>();

        // 获取总页数
        page.setRows(discussPostService.findDiscussPostRows(0));
        page.setPath("/index?orderMode=" + orderMode);

        // 分页查询
        List<DiscussPost> list = discussPostService.findDiscussPosts(0, page.getOffset(), page.getLimit(), orderMode, null, null, 0);
        // 封装帖子和该帖子对应的用户信息
        List<Map<String, Object>> discussPosts = new ArrayList<>();
        if (list != null) {
            list.forEach(post -> {
                if (post != null) {
                    discussPosts.add(getPostMapVO(post));
                }
            });
        }

        JSONArray result = (JSONArray) JSONArray.toJSON(discussPosts);
        page.setResult(result);
        hashMap.put("discussPosts", page);

        hashMap.put("orderMode", orderMode);

        return new Result("success", Result.SUCCESS, hashMap);
    }

    /**
     * 进入帖子详情页
     *
     * @param discussPostId
     * @return
     */
    @GetMapping("/detail/{discussPostId}")
    @ResponseBody
    public Result getDiscussPost(@PathVariable("discussPostId") int discussPostId) {
        HashMap<String, Object> resultMap = new HashMap<>();

        // 帖子
        DiscussPost discussPost = discussPostService.findDiscussPostById(discussPostId);
        if (discussPost == null) {
            return new Result("fail", "1", "没有找到帖子");
        }
        if (discussPost.getStatus() == 1) {
            discussPost.setContent("该帖子因违反社区规范，已无法查看");
            discussPost.setPicUrls(null);
        } else {
            String content = HtmlUtils.htmlUnescape(discussPost.getContent()); // 内容反转义，不然 markDown 格式无法显示
            discussPost.setContent(content);
        }

        //将discuss_post表中以 , 分隔的pic_url转为json数组返回到前端
        resultMap.put("post", discussPostService.toDiscussPostJsonObject(discussPost));

        // 作者
        User user = userService.findUserById(discussPost.getUserId());
        resultMap.put("user", user);

        // 当前登录用户的点赞状态
        int likeStatus = getUser() == null ? 0 :
                likeService.findEntityLikeStatus(getUser().getId(), ENTITY_TYPE_POST, discussPostId);
        resultMap.put("likeStatus", likeStatus);

        // 增加浏览帖子经验
        if (getUser() != null) {
            Event event = new Event()
                    .setTopic(TOPIC_EXP)
                    .setUserId(getUser().getId())
                    .setData("type", ExpType.EXP_BROWSE.getName());
            eventProducer.fireEvent(event);
        }

        // 增加帖子浏览量
        discussPostService.viewPost(discussPost.getId());

        discussPostService.addDisscussPostToRefreshScore(discussPost.getId());

        return new Result("success", Result.SUCCESS, resultMap);
    }


    /**
     * 搜索
     * search?keword=xxx&current=2&limit=2
     *
     * @param keyword 关键词
     * @param page
     * @return
     */
    @PostMapping("/search")
    public Result search(String keyword, Page page) {
        JSONObject jsonObject = new JSONObject();
        // 搜索帖子 (Spring 提供的 Page 当前页码从 0 开始计数)
        org.springframework.data.domain.Page<DiscussPost> searchResult = elasticsearchService.searchDiscussPost(keyword, page.getCurrent() - 1, page.getLimit());
        // 聚合数据
        List<Map<String, Object>> discussPosts = new ArrayList<>();
        if (searchResult != null) {
            searchResult.forEach(post -> {
                if (post != null) {
                    discussPosts.add(getPostMapVO(post));
                }
            });
        }

        // 设置分页
        page.setPath("/search?keyword=" + keyword);
        page.setRows(searchResult == null ? 0 : (int) searchResult.getTotalElements());

        jsonObject.put("keyword", keyword);
        JSONArray result = (JSONArray) JSONArray.toJSON(discussPosts);
        page.setResult(result);
        jsonObject.put("discussPosts", discussPosts);

        return new Result("success", Result.SUCCESS, jsonObject);
    }

    /**
     * 将帖子封装成Map
     *
     * @param post
     * @return
     */
    private Map<String, Object> getPostMapVO(DiscussPost post) {
        Map<String, Object> map = new HashMap<>();
        // 帖子
        // 将discuss_post表中以 , 分隔的pic_url转为json数组返回到前端
        map.put("post", discussPostService.toDiscussPostJsonObject(post));
        // 作者
        map.put("user", userService.findUserById(post.getUserId()));
        // 点赞数量
        map.put("likeCount", likeService.findEntityLikeCount(ENTITY_TYPE_POST, post.getId()));
        // 当前登录用户的点赞状态
        int likeStatus = getUser() == null ? 0 :
                likeService.findEntityLikeStatus(getUser().getId(), ENTITY_TYPE_POST, post.getId());
        map.put("likeStatus", likeStatus);
        return map;
    }

    /**
     * 置顶帖子
     *
     * @return
     */
    @PostMapping("/top")
    @ResponseBody
    public Result updateTop(@RequestBody HashMap<String, Integer> map) {
        int id = map.get("id");
        int type = map.get("type");

        discussPostService.updateType(id, type);

        // 触发发帖事件，通过消息队列将其存入 Elasticsearch 服务器
        Event event = new Event()
                .setTopic(TOPIC_PUBLISH)
                .setUserId(getUser().getId())
                .setEntityType(ENTITY_TYPE_POST)
                .setEntityId(id);
        eventProducer.fireEvent(event);

        return new Result("success", Result.SUCCESS, "置顶成功");
    }

    /**
     * 禁用帖子（管理员操作）
     *
     * @return
     */
    @PostMapping("/disable/{id}")
    public Result setDisable(@PathVariable int id) {
        discussPostService.updateStatus(id, 1);

        // 触发删帖事件，通过消息队列更新 Elasticsearch 服务器
        Event event = new Event()
                .setTopic(TOPIC_DELETE)
                .setUserId(getUser().getId())
                .setEntityType(ENTITY_TYPE_POST)
                .setEntityId(id);
        eventProducer.fireEvent(event);

        return new Result("success", Result.SUCCESS, "禁用成功");
    }

    /**
     * 删除帖子（只能自己删除自己的）
     *
     * @return
     */
    @PostMapping("/delete/{id}")
    @ResponseBody
    public Result setDelete(@PathVariable int id) {
        DiscussPost discussPost = discussPostService.findDiscussPostById(id);
        if (discussPost == null || discussPost.getUserId() != getUser().getId()) {
            return new Result("fail", "1", "只能删除自己的帖子");
        }

        discussPostService.updateStatus(id, 2);

        // 触发删帖事件，通过消息队列更新 Elasticsearch 服务器
        Event event = new Event()
                .setTopic(TOPIC_DELETE)
                .setUserId(getUser().getId())
                .setEntityType(ENTITY_TYPE_POST)
                .setEntityId(id);
        eventProducer.fireEvent(event);

        return new Result("success", Result.SUCCESS, "删除成功");
    }
}
